package com.ats.audiotoscore;

import android.graphics.*;
import android.util.AttributeSet;
import android.content.Context;
import android.view.View;
//import android.util.Log;

class SpectrumView extends View {
//	private static final String TAG = "AudioToScore";
	private PitchDetection pd = null;
	private AudioCapture ac = null;
	private AudioProcess ap = null;
	private boolean showInfo = true;
	private Paint paint = null;

	public SpectrumView(Context context, AttributeSet attrs) {
		super(context, attrs);
		paint = new Paint();
	}

	private void DrawMeter(Canvas canvas, double db) {
		int meterW = 5;
		int meterH = this.getHeight();
		int spY = GetSpectrumY(db);

		paint.setStrokeWidth(1);
		paint.setColor(Color.BLACK);
		canvas.drawRect(0, 0, meterW-1, meterH-1, paint);
		for (int y=1; y<meterH-2; y++) {
			int c = Color.WHITE;
			if (spY < y) {
				int pct = 100 - (y * 100) / meterH; 
				int d = (y * 256) / meterH;
				if (pct < 60)
					c = 0xff000000 | (d<<8);
				else if (pct < 80)
					c = 0xff000000 | (d<<16) | (d<<8);
				else
					c = 0xff000000 | (d<<16);
			}
			paint.setColor(c);
			canvas.drawLine(1, y, meterW-2, y, paint);
		}
	}

	private int GetSpectrumY(double db) {
		int h = this.getHeight();
		if (db < 0) db = 0;
		if (db > 120) db = 120;
		int y = (int)((db / 120) * h);
		return h - y;
	}

	private void DrawSpectrum(Canvas canvas) {
		double samples[] = pd.GetFFTOutput();
		Peak peaks[] = pd.GetPeaks();

		if (samples != null) {
			paint.setStrokeWidth(2);
			paint.setColor(Color.BLACK);
			for (int i=1; i<samples.length/2; i++) {
				int x = i-1;
				canvas.drawLine(x, GetSpectrumY(samples[i]), x+1, GetSpectrumY(samples[i+1]), paint);
			}
			int y = GetSpectrumY(ap.getRealRmsdB()+10);

			paint.setStrokeWidth(1);
			paint.setColor(Color.GREEN);
			canvas.drawLine(0, y, canvas.getWidth()-1, y, paint);

			paint.setStrokeWidth(4);
			paint.setColor(Color.RED);
			for (int i=0; i<peaks.length; i++) {
				if (peaks[i].db != 0) {
					int x = peaks[i].index-1;
					canvas.drawCircle(x, GetSpectrumY(peaks[i].db), 2.f, paint);
				}
			}
		}
	}

	private void DrawInfo(Canvas canvas) {
		String str = "";
		if (pd.GetDetectedPitch() != 0) {
			str = String.format("RmsdB=%.2f detectedPitch=%s (%.2f) pd=%d\n", ap.getRmsdB(), pd.HzToNote(pd.GetDetectedPitch()), pd.GetDetectedPitch(), pd.GetPitchConfidence());
		} else {
			str = String.format("RmsdB=%.2f\n", ap.getRmsdB());
		}
		str = String.format("%sSamples/Secs=%d  Rate=%d CPU=%.2fMhz\n", str, ac.getSamplesPerSecond(), ac.getSampleRate(), Utils.GetCPUSpeed() / 1000.0);
		str = String.format("%sBufferSize=%d\n", str, pd.GetFFTOutput().length);

		paint.setStyle(Paint.Style.FILL);
		paint.setStrokeWidth(1);
		paint.setColor(Color.BLACK);
		paint.setTextSize(12);
		int x = 20, y = 20;
		for (String line: str.split("\n")) {
		      canvas.drawText(line, x, y, paint);
		      y+= -paint.ascent()+paint.descent();
		}

	}

	public void DrawSamples(PitchDetection _pd, AudioCapture _ac, AudioProcess _ap) {
		pd = _pd;
		ac = _ac;
		ap = _ap;
		invalidate();
		requestLayout();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		if (pd == null || ac == null)
			return;

		if (showInfo) {
			DrawInfo(canvas);
		}

		DrawSpectrum(canvas);
		DrawMeter(canvas, ap.getRmsdB());
	}
}
